package com.fla.shapeevader.ui;

import java.util.ArrayList;
import java.util.List;

import com.fla.shapeevader.ui.drawers.BaseShapeDrawer;
import com.fla.shapeevader.ui.drawers.UserShapeDrawer;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class GameStateDrawerThread extends Thread {
    public static final String INTERSECTION_OCCURED_KEY = "INTERSECTION_OCCURED_KEY";

    private SurfaceHolder surfaceHolder;
    private Context context;
    private Handler handler;

    private int canvasWidth;
    private int canvasHeight;

    private UserShapeDrawer userShape;

    private List<BaseShapeDrawer> shapes;

    private boolean downEvent = false;
    private boolean run = false;

    public GameStateDrawerThread(SurfaceHolder surfaceHolder, Context context, Handler handler) {
        this.surfaceHolder = surfaceHolder;
        this.handler = handler;
        this.context = context;

        shapes = new ArrayList<BaseShapeDrawer>();
    }

    private int firstIndex = -1;

    public void dispatchTouchEvent(MotionEvent event) {
        synchronized (surfaceHolder) {


            if ((event.getAction() == MotionEvent.ACTION_DOWN)
                || (event.getAction() == MotionEvent.ACTION_POINTER_DOWN)
                || (event.getAction() == MotionEvent.ACTION_POINTER_1_DOWN)
                || (event.getAction() == MotionEvent.ACTION_POINTER_2_DOWN)
                || (event.getAction() == MotionEvent.ACTION_POINTER_3_DOWN)) {
                Log.d("test", "action down");
                firstIndex = getContainedPointerIndex(userShape, event);
            }

            if (firstIndex >= 0) {
                handleUserAction(userShape, event, firstIndex);
            }
        }
    }

    private int getContainedPointerIndex(UserShapeDrawer u, MotionEvent event) {
        RectF userBounds = u.getShape().getBounds();

        for (int i = 0; i < event.getPointerCount(); i++) {
            if (userBounds.contains(event.getX(i), event.getY(i))) {
                return i;
            }
        }
        return -1;
    }

    private void handleUserAction(UserShapeDrawer u, MotionEvent event, int pointerIndex) {
        RectF userBounds = u.getShape().getBounds();

        Log.d("test", String.format("pointerIndex=%s, x=%s", pointerIndex, event.getX(pointerIndex)));
        
        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            float newLeft = event.getX(pointerIndex) - userBounds.width() / 2;
            float newTop = event.getY(pointerIndex) - userBounds.height() / 2;

            // user cannot leave the screen
            newLeft = newLeft < 0 ? 0 : newLeft;
            newTop = newTop < 0 ? 0 : newTop;

            if (newLeft + userBounds.width() > canvasWidth) {
                newLeft = canvasWidth - userBounds.width();
            }

            if (newTop + userBounds.height() > canvasHeight) {
                newTop = canvasHeight - userBounds.height();
            }

            userBounds.offsetTo(newLeft, newTop);
        }
    }

    public void setUserShape(UserShapeDrawer userShape) {
        this.userShape = userShape;
    }

    public void addShape(BaseShapeDrawer shape) {
        shape.setSize(canvasWidth, canvasHeight);
        shapes.add(shape);
    }

    public void setRunning(boolean b) {
        run = b;
    }

    public void setSurfaceSize(int width, int height) {
        // synchronized to make sure these all change atomically
        synchronized (surfaceHolder) {
            canvasWidth = width;
            canvasHeight = height;

            // dispath size changed
            for (BaseShapeDrawer shape : shapes) {
                shape.setSize(canvasWidth, canvasHeight);
            }
        }
    }

    @Override
    public void run() {
        while (run) {
            Canvas c = null;
            try {
                c = surfaceHolder.lockCanvas(null);
                if (c == null) {
                    continue;
                }
                synchronized (surfaceHolder) {
                    // clear background
                    c.drawColor(Color.BLACK);

                    userShape.drawOnCanvas(c);
                    // dispathDraw
                    for (BaseShapeDrawer shape : shapes) {
                        if (userShape.checkIntersection(shape)) {
                            // report about intersection
                            Message msg = handler.obtainMessage();
                            Bundle b = new Bundle();
                            b.putBoolean(INTERSECTION_OCCURED_KEY, true);
                            msg.setData(b);
                            handler.sendMessage(msg);

                            userShape.setHappy(false);
                            userShape.drawOnCanvas(c);

                            run = false;
                            shape.drawOnCanvas(c);
                            continue;
                        }

                        shape.getShape().makeMove();
                        shape.drawOnCanvas(c);
                    }
                }
            }
            finally {
                // do this in a finally so that if an exception is thrown
                // during the above, we don't leave the Surface in an
                // inconsistent state
                if (c != null) {
                    surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }

}
